import { CameraApplication } from "../lib/CameraApplication";
import { GLProgram } from "../webgl/WebGLProgram";
import { HttpRequest } from "../common/utils/HttpRequest";
import { Quake3BspScene } from "../lib/Quake3BspScene";
import { Q3BspParser as Quake3BspParser } from "../lib/Quake3BspParser";
import { GLProgramCache } from "../webgl/WebGLProgramCache";

export class Q3BspApplication extends CameraApplication
{
    public bspScene: Quake3BspScene; // 引用了Quake3BspScene类
    public program: GLProgram; // 引用了一个GLProgram类

    public constructor ( canvas: HTMLCanvasElement )
    {
        super( canvas );
        this.bspScene = new Quake3BspScene( this.gl ); // 创建Quake3BspScene对象
        this.program = GLProgramCache.instance.getMust( "texture" ); // 获取默认的纹理着色器对象
        this.camera.y = 6; // 设置摄像机的高度
    }

    public render (): void
    {
        this.bspScene.draw( this.camera, this.program );
    }

    public async run (): Promise<void>
    {
        // 1、创建Quake3BspParser对象，用来解析二进制的BSP文件格式
        let parser: Quake3BspParser = new Quake3BspParser(); 
        // 2、使用HttpRequest的loadArrayBufferAsync静态方法从服务器某个路径载入.bsp文件
        let buffer: ArrayBuffer = await HttpRequest.loadArrayBufferAsync( this.bspScene.pathPrifix + "test1_paul.bsp" );
        // 3、注意上面载入bsp二进制数据时使用了await关键字对资源进行同步
        // 因此确保parse方法调用时，buffer是有数据的。
        // 如果上面方法不使用await，那么loadArrayBufferAsync是异步调用
        // parse方法调用时，buffer极大几率是个空对象，切记！
        parser.parse( buffer );
        // 4、当解析完成bsp文件后，调用bspScene的loadTextures方法，从服务器上载入相应的各种纹理
        // 需要注意的是，这里也使用了await关键字
        await this.bspScene.loadTextures( parser );
        // 5、一旦所有纹理都载入了后，就调用bspScene的compileMap方法生成GLStaticMesh对象
        this.bspScene.compileMap( parser );
        // 6、资源全局加载完成以及渲染数据都组装完成后，进入游戏循环
        super.run();
    }
}